<!--
 * @Author: Wushiqi
 * @Descripttion: 宏任务微任务
 * @Date: 2021-04-28 15:59:58
 * @LastEditor: Wushiqi
 * @LastEditTime: 2021-04-28 17:12:56
-->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    async function async1() {
      console.log('async1 start')
      await async2()
      console.log('async1 end')
    }
    async function async2() {
      console.log('async2')
    }
    async1()
    console.log('script start')
    // 执行到await时，如果返回的不是一个promise对象，
    // await会阻塞下面代码(当前async代码块的代码)，
    // 会先执行async外的同步代码(在这之前先看看await中函数的同步代码，先把同步代码执行完)，
    // 等待同步代码执行完之后，再回到async内部继续执行
    
    // 执行到await时，如果返回的是一个promise对象，
    // await会阻塞下面代码(当前async代码块的代码)，
    // 会先执行async外的同步代码(在这之前先看看await中函数的同步代码，先把同步代码执行完)，
    // 等待同步代码执行完之后，再回到async内部等promise状态达到fulfill的时候再继续执行下面的代码
    //所以结果为
    // async1 start
    // async2
    // script start
    // async1 end

    console.log('start')

    setTimeout(() => {
      console.log('setTimeout')
    }, 0)

    new Promise((resolve) => {
      console.log('promise')
      resolve()
    })
      .then(() => {
        console.log('then1')
      })
      .then(() => {
        console.log('then2')
      })

    console.log('end')
    // 主线程
    // start
    // promise
    // end
    // 微任务
    // then1
    // then2
    // 宏任务
    // setTimeout

    console.log('script start')
    async function async1() {
      await async2()
      console.log('async1 end')
    }
    async function async2() {
      console.log('async2 end')
    }
    async1()

    setTimeout(function() {
      console.log('setTimeout')
    }, 0)

    new Promise(resolve => {
      console.log('Promise')
      resolve()
    })
      .then(function() {
        console.log('promise1')
      })
      .then(function() {
        console.log('promise2')
      })
    console.log('script end')
    // 主线程
    // script start
    // async2 end
    // Promise
    // script end
    // 微任务
    // async1 end
    // promise1
    // promise2
    // 宏任务
    // setTimeout


    console.log('1主线程');					//整体script作为第一个宏任务进入主线程
    setTimeout(function() {				//setTimeout，其回调函数被分发到宏任务Event Queue（执行规则：从上到下排序，先进先执行）中
      console.log('2宏任务');
      process.nextTick(function() {
          console.log('3宏任务里面的微任务');
      })
      new Promise(function(resolve) {
          console.log('4微任务');
          resolve();
      }).then(function() {
          console.log('5微任务')
      })
    })
    process.nextTick(function() {	//process.nextTick()其回调函数被分发到微任务Event Queue中
      console.log('6微任务');
    })
    new Promise(function(resolve) {		//Promise，new Promise直接执行，输出7
      console.log('7微任务');
      resolve();
    }).then(function() {
      console.log('8微任务')			//then被分发到微任务Event Queue中,排在process.nextTick微任务后面。
    })
    setTimeout(function() {			//setTimeout，其回调函数被分发到宏任务Event Queue中,排在前面的setTimeout后面
      console.log('9宏任务');
      process.nextTick(function() {
          console.log('10宏任务里面的微任务');
      })
      new Promise(function(resolve) {
          console.log('11微任务');
          resolve();
      }).then(function() {
          console.log('12微任务')
      })
    })
    // 1主线程
    // 7微任务
    // 6微任务
    // 8微任务
    // 2宏任务
    // 4微任务
    // 3宏任务里面的微任务
    // 5微任务
    // 9宏任务
    // 11微任务
    // 10宏任务里面的微任务
    // 12微任务

    async function async1() {
      console.log('async1 start')
      await async2()
      console.log('async1 end')
    }
    async function async2() {
      console.log('async2')
    }
    async1()
    console.log('script end')
    // async1 start
    // async2
    // script end
    // async1 end

    setTimeout(function(){
      console.log('1') // 宏任务
    });
    new Promise(function(resolve){
      console.log('2'); // 宏任务，在主线程
      resolve();
    }).then(function(){
      console.log('3') // 微任务
    });
    console.log('4'); // 主线程
    new Promise(function(resolve){
      console.log('5'); // 主线程
      resolve();
    }).then(function(){
      console.log('6') // 微任务
    });
    setTimeout(function(){
      console.log('7') // 宏任务
    });
    function bar(){
      console.log('8')
      foo()
    }
    function foo(){
      console.log('9')
    }
    console.log('10') // 主线程
    bar()
    // 主线程
    // 2
    // 4
    // 5
    // 10
    // 8
    // 9
    // 微任务Event Queue
    // 3
    // 6
    // 宏任务Event Queue
    // 1
    // 7
    
    setTimeout(() => {
      console.log('1');
      new Promise(function (resolve, reject) {
        console.log('2');
        setTimeout(() => {
          console.log('3');
          setTimeout(() => {
            console.log('13');
          }, 0);
        }, 0);
        resolve();
      }).then(function () {
        console.log('4')
      })
    }, 0);
    console.log('5');
    setTimeout(() => {
      console.log('6');
      setTimeout(() => {
        console.log('12');
      }, 0);
    }, 0);
    new Promise(function (resolve, reject) {
      console.log('7');
      // reject();
      resolve();
    }).then(function () {
      console.log('8')
      setTimeout(() => {
        console.log('14');
      }, 0);
    }).catch(function () {
      console.log('9')
    })
    console.log('10');
    // 5 7 10 8 1 2 4 6 14 3 12 13
    // 主线程
    // 5
    // 7
    // 10
    // 微任务
    // 8
        // 宏任务
        // 14
    // 宏任务
    // 1
        // 主线程
        // 2
        // 微任务
        // 4
        // 宏任务(在外层的宏任务之后执行)
        // 3
            // 宏任务
            // 13
    // 6
        // 宏任务（同级宏任务按顺序执行）
        // 12
  </script>
</body>
</html>